<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // 原型： 2种原型 ： 1.显示原型  2.隐式原型；
      // 1.显示原型（prototype） 是构造函数的 ：在你声明一个函数的时候 也会声明一个原型出来；
      // 构造函数 有 自身和显示原型共同构成
      // 原型其实就是一个预定义的对象；
      // function Person(){
      //     console.log(this);
      //     this.name = "张三";
      // }
      // // console.log(Person.prototype); // 显示原型；
      // Person.prototype.fn = function(){
      //     console.log(123);
      // }

      // Person.prototype.fn2 = function(){
      //     console.log(456);
      // }

      // 2.隐式原型(__proto__,[[prototype]]) ： 每个对象  都会有一个隐式原型
      // 对象由2个部分构成 ：1.自身的属性和方法 2.隐式原型的属性和方法；
      // let obj = {
      //     name:"张三"
      // }
      // console.log(obj);

      // 3.显示原型和隐式原型的关系；
      // function Person(){
      //     this.name = "张三";
      //     // this.fn = function(){
      //     //     console.log("fn");
      //     // }
      // }
      // Person.prototype.fn = function(){
      //     console.log("fn");
      // }

      // let obj = new Person();
      // // console.log(obj);
      // // 显示原型是构造函数的  隐式原型是对象的 。其实2个都是一样的只是名称不同而已；
      // console.log(Person.prototype===obj.__proto__);

      // 4.原型的固有属性constructor； 原型的固有属性constructor会指向 构造函数本身；
      // 原型会有一个自带的属性  constructor 在指向 构造函数本身；
      function Person() {
        this.name = "张三";
      }
      //   console.log(Person.prototype.constructor);

      // 会覆盖掉prototype 的固有属性 constructor ；
      //   Person.prototype = {
      //     fn: function () {
      //       console.log("fn");
      //     },
      //   };
      //   Person.prototype.constructor = Person;

      // 不会覆盖原本的constructor；
      Person.prototype.fn = function () {
        console.log("fn");
      };
      let zhangsan = new Person();
      zhangsan.fn();
    </script>
  </body>
</html>
